Don't save Xen heap pages during domain save
authorKeir Fraser <keir.fraser@citrix.com>
Tue, 15 Jun 2010 12:18:09 +0000 (13:18 +0100)
committerKeir Fraser <keir.fraser@citrix.com>
Tue, 15 Jun 2010 12:18:09 +0000 (13:18 +0100)
As discussed in the thread starting at
http://lists.xensource.com/archives/html/xen-devel/2010-05/msg01383.html,
don't save Xen heap pages in order to avoid overallocation when the
domain gets restored, as those pages would get (temporarily) backed
with normal RAM pages by the restore code.

This requires making DOMCTL_getpageframeinfo{2,3} usable for HVM
guests, meaning that the input to these must be treated as GMFNs.

Signed-off-by: Jan Beulich <jbeulich@novell.com>
tools/libxc/xc_domain_save.c
xen/arch/x86/domctl.c

index 2cc8a8cf2349ad12a94ca9b2e71780e5ee1f4974..cc6bd1318e68464f7f3593b20afe31498593a8f3 100644 (file)
@@ -1288,58 +1288,64 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
                 goto out;
             }
 
-            if ( hvm )
+            /* Get page types */
+            if ( xc_get_pfn_type_batch(xch, dom, batch, pfn_type) )
             {
-                /* Look for and skip completely empty batches. */
-                for ( j = 0; j < batch; j++ )
-                {
-                    if ( !pfn_err[j] )
-                        break;
-                    pfn_type[j] |= XEN_DOMCTL_PFINFO_XTAB;
-                }
-                if ( j == batch )
-                {
-                    munmap(region_base, batch*PAGE_SIZE);
-                    continue; /* bail on this batch: no valid pages */
-                }
-                for ( ; j < batch; j++ )
-                    if ( pfn_err[j] )
-                        pfn_type[j] |= XEN_DOMCTL_PFINFO_XTAB;
+                PERROR("get_pfn_type_batch failed");
+                goto out;
             }
-            else
+
+            for ( run = j = 0; j < batch; j++ )
             {
-                /* Get page types */
-                if ( xc_get_pfn_type_batch(xch, dom, batch, pfn_type) )
-                {
-                    PERROR("get_pfn_type_batch failed");
-                    goto out;
-                }
+                unsigned long gmfn = pfn_batch[j];
 
-                for ( j = 0; j < batch; j++ )
+                if ( !hvm )
+                    gmfn = pfn_to_mfn(gmfn);
+
+                if ( pfn_err[j] )
                 {
-                    unsigned long mfn = pfn_to_mfn(pfn_batch[j]);
-                    
                     if ( pfn_type[j] == XEN_DOMCTL_PFINFO_XTAB )
-                    {
-                        DPRINTF("type fail: page %i mfn %08lx\n", 
-                                j, mfn);
                         continue;
-                    }
-                    
-                    if ( debug )
+                    DPRINTF("map fail: page %i mfn %08lx err %d\n",
+                            j, gmfn, pfn_err[j]);
+                    pfn_type[j] = XEN_DOMCTL_PFINFO_XTAB;
+                    continue;
+                }
+
+                if ( pfn_type[j] == XEN_DOMCTL_PFINFO_XTAB )
+                {
+                    DPRINTF("type fail: page %i mfn %08lx\n", j, gmfn);
+                    continue;
+                }
+
+                /* canonicalise mfn->pfn */
+                pfn_type[j] |= pfn_batch[j];
+                ++run;
+
+                if ( debug )
+                {
+                    if ( hvm )
+                        DPRINTF("%d pfn=%08lx sum=%08lx\n",
+                                iter,
+                                pfn_type[j],
+                                csum_page(region_base + (PAGE_SIZE*j)));
+                    else
                         DPRINTF("%d pfn= %08lx mfn= %08lx [mfn]= %08lx"
                                 " sum= %08lx\n",
                                 iter,
-                                pfn_type[j] | pfn_batch[j],
-                                mfn,
-                                mfn_to_pfn(mfn),
+                                pfn_type[j],
+                                gmfn,
+                                mfn_to_pfn(gmfn),
                                 csum_page(region_base + (PAGE_SIZE*j)));
-                    
-                    /* canonicalise mfn->pfn */
-                    pfn_type[j] |= pfn_batch[j];
                 }
             }
 
+            if ( !run )
+            {
+                munmap(region_base, batch*PAGE_SIZE);
+                continue; /* bail on this batch: no valid pages */
+            }
+
             if ( wrexact(io_fd, &batch, sizeof(unsigned int)) )
             {
                 PERROR("Error when writing to state file (2)");
index 2fc24c9fd748803c58ce52d7e61d589235bf108f..fdbdb2210e011e86e34c93341d9b3872e7af49c1 100644 (file)
@@ -207,11 +207,12 @@ long arch_do_domctl(
 
                 for ( j = 0; j < k; j++ )
                 {
-                    unsigned long type = 0, mfn = arr[j];
+                    unsigned long type = 0, mfn = gmfn_to_mfn(d, arr[j]);
 
                     page = mfn_to_page(mfn);
 
-                    if ( unlikely(!mfn_valid(mfn)) )
+                    if ( unlikely(!mfn_valid(mfn)) ||
+                         unlikely(is_xen_heap_mfn(mfn)) )
                         type = XEN_DOMCTL_PFINFO_XTAB;
                     else if ( xsm_getpageframeinfo(page) != 0 )
                         ;
@@ -306,14 +307,15 @@ long arch_do_domctl(
             for ( j = 0; j < k; j++ )
             {      
                 struct page_info *page;
-                unsigned long mfn = arr32[j];
+                unsigned long mfn = gmfn_to_mfn(d, arr32[j]);
 
                 page = mfn_to_page(mfn);
 
                 if ( domctl->cmd == XEN_DOMCTL_getpageframeinfo3)
                     arr32[j] = 0;
 
-                if ( unlikely(!mfn_valid(mfn)) )
+                if ( unlikely(!mfn_valid(mfn)) ||
+                     unlikely(is_xen_heap_mfn(mfn)) )
                     arr32[j] |= XEN_DOMCTL_PFINFO_XTAB;
                 else if ( xsm_getpageframeinfo(page) != 0 )
                     continue;